/* 
 * Copyright 2013 Imanuel Rohlfing, Dennis Wittkötter

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
package management.ejb;


import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import management.entities.*;


/**
 * The database controller provides access to the database and provides
 * several operations to persist objects to the database.
 * @author Imanuel Rohlfing
 */
@Stateless
public class DatabaseController {
    
    /**
     * the entitiy manager
     */
    @PersistenceContext(unitName="ZugangsVerwaltungPU")
    private EntityManager em;
    
    /**
     * Persists an object to the database.
     * @param obj   the object to persist
     * @return  'true' if persistance was successful, 'false' if not.
     */
    public boolean persist(Object obj) {
        try {
            em.persist(obj);
            return true;
        } catch(Exception e) { }
        return false;
    }
    
    /**
     * Updates an object in the database.
     * @param obj   The object to update.
     * @return  'true' if update was successful, 'false' if not.
     */
    public boolean update(Object obj) {
        try {
            em.merge(obj);
            return true;
        } catch(Exception e) {}
        return false;
    }
    
    /**
     * Deletes an object from the database.
     * @param obj   The Object to delete.
     * @return  'true' if deleting was successful, 'false' if not.
     */
    public boolean delete(Object obj) {
        try {
            Object o = em.merge(obj);
            em.remove(o);
            return true;
        } catch(Exception e) { }
        return false;
    }
    
    /**
     * Provides all rooms from the database.
     * @return  a list of rooms
     */
    public List<Room> getRooms() {
        return em.createQuery("SELECT r FROM Room r", Room.class).getResultList();
    }
    
    /**
     * Provides the room with the commited id.
     * @param roomId    the id of the wanted room.
     * @return  the wanted room
     */
    public Room findRoom(String roomId) {   
        try {
            return em.find(Room.class, Integer.parseInt(roomId));
        } catch(Exception e) {
            System.err.println("Fehler beim Finden des Raumes: ID-" + roomId);
        }
        return null;
    }
    
     /**
     * Check, if room  already exists.
     * @param r    the room to be checked
     * @return  'true' if number exists, 'false' if not
     */
    public boolean roomExists(Room r) {   
        List<Room> results;
        try {
            results = em.createQuery("SELECT r FROM Room r WHERE r.name =:n AND r.building =:b AND r.id !=:id", Room.class)
                            .setParameter("n", r.getName())
                            .setParameter("b", r.getBuilding())
                            .setParameter("id", r.getId())
                            .getResultList();
            if(results.isEmpty()){
                return false;
            }
        } catch(Exception e) {
            System.err.println("Fehler beim Finden des Raumes");
        }
        return true;
    }      
    
    
    
    /**
     * Provides all persons from the database.
     * @return  a list of persons
     */
    public List<Person> getPersons() {
        return em.createQuery("SELECT p FROM Person p", Person.class).getResultList();
    } 
     
    /**
     * Provides the person with the commited id.
     * @param personId  the id of the wnated person
     * @return  the wanted person
     */
    public Person findPerson(String personId) {   
        try {
            return em.find(Person.class, Integer.parseInt(personId));
        } catch(Exception e) {
            System.err.println("Fehler beim Finden der Person: ID-" + personId);
        }
        return null;
    }    

    /**
     * Check, if identity card numer already exists.
     * @param p    the person to be checked
     * @return  'true' if number exists, 'false' if not
     */
    public boolean identityCardNumberExists(Person p) {   
        List<Person> results;
        try {
            results = em.createQuery("SELECT p FROM Person p WHERE p.identityCardNumber =:number AND p.id !=:id", Person.class)
                            .setParameter("number", p.getIdentityCardNumber())
                            .setParameter("id", p.getId())
                            .getResultList();
            if(results.isEmpty()){
                return false;
            }
        } catch(Exception e) {
            System.err.println("Fehler beim Finden der Person mit der Karten-Nr: " + p.getIdentityCardNumber());
        }
        return true;
    }       

    /**
     * Provides all users from the database.
     * @return  a list of users
     */
    public List<IntUser> getIntUsers() {
        return em.createQuery("SELECT u FROM IntUser u", IntUser.class).getResultList();
    } 
     
    /**
     * Provides the user with the commited id.
     * @param userId    the id of the wanted user
     * @return  the wanted user
     */
    public IntUser findIntUser(String userId) {   
        try {
            return em.find(IntUser.class, Integer.parseInt(userId));
        } catch(Exception e) {
            System.err.println("Fehler beim Finden des Users: ID-" + userId);
        }
        return null;
    }   
     
    /**
     * Searches for an user in the database.
     * If the user already exists, it will provided by the method.
     * @param u the user to search for.
     * @return  the located user if existing, otherwise 'null'
     */
    public IntUser findIntUser(IntUser u){
         List<IntUser> results;
         
         // Falls kein Admin --> erzeugen
        results = em.createQuery("SELECT u FROM IntUser u", IntUser.class).getResultList();
        if( results.isEmpty() ){
            persist(new IntUser("admin", "admin"));
            results = null;
        }
         
        results = em.createQuery("select u from IntUser u where u.username=:username and u.password=:password")
                .setParameter("username", u.getUsername())
                .setParameter("password", u.getPassword())
                .getResultList();

        if ( !results.isEmpty() ) {
            return results.get(0);
        }
        return null;
    }
    
      /**
     * Check, if IntUser already exists.
     * @param user    the IntUser to be checked
     * @return  'true' if number exists, 'false' if not
     */
    public boolean intUserExists(IntUser user) {   
        List<IntUser> results;
        try {
            results = em.createQuery("SELECT u FROM IntUser u WHERE u.username =:n u.id !=:id", IntUser.class)
                            .setParameter("n", user.getUsername())
                            .setParameter("id", user.getId())
                            .getResultList();
            if(results.isEmpty()){
                return false;
            }
        } catch(Exception e) {
            System.err.println("Fehler beim Finden des Users");
        }
        return true;
    }    
    
}
